package es.mfp.practicos.util;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;

import es.mfp.practicos.DTO.LineaFacturaSalida;
import es.mfp.practicos.DTO.LineaInformeFactura;
import es.mfp.practicos.DTO.TotalFactura;
import es.mfp.practicos.domain.Empleado;
import es.mfp.practicos.domain.LineaFactura;
import es.mfp.practicos.domain.Parametros;
import es.mfp.practicos.domain.TipoLinea;
import es.mfp.practicos.service.ParametrosService;
import es.mfp.practicos.web.context.AppContext;

public final class FacturaUtils {

	/**
	 * Actualiza el total de la factura
	 */
	public static TotalFactura totalizar(Collection<LineaFactura> lineas) {

		TotalFactura total = new TotalFactura();

		if (lineas == null || lineas.isEmpty()) {
			return total;
		}

		for (LineaFactura lf : lineas) {

			total.setPuntosAcumulados(total.getPuntosAcumulados()
					+ lf.getPuntosAcumulados());

			total.setTotalConsumido(total.getTotalConsumido()
					+ lf.getImporteConsumido());

			total.setTotalFacturado(total.getTotalFacturado()
					+ lf.getImporteTotal());

			total.setTotalIva(total.getTotalIva() + lf.getImporteIva());

		}

		return total;

	}

	/**
	 * Establece la relacion entre el importe consumido y los puntos a acumular
	 */
	public static Integer calcularPuntos(final Double importeConsumido) {

		ApplicationContext ctx = AppContext.getApplicationContext();
		ParametrosService parametrosService = ctx
				.getBean(ParametrosService.class);

		if (importeConsumido == null) {
			return 0;
		}

		// por ahora es una relacion 100%
		Double res = parametrosService.buscarViegente()
				.getRelacionPuntosConsumo() * importeConsumido;

		return CurrencyUtils.roundToInteger(res);
	}

	// factory..
	/**
	 * Determinamos tipo descuento/iva aplicado
	 */
	public static LineaFacturaSalida calcularLineaFacturaSalida(
			final LineaFactura lf) {

		ApplicationContext ctx = AppContext.getApplicationContext();
		ParametrosService parametrosService = ctx
				.getBean(ParametrosService.class);

		LineaFacturaSalida res = new LineaFacturaSalida(lf);

		Parametros vigente = parametrosService.buscarViegente();

		// con iva y sin descuento
		if (lf.getLineaTelefonica().getTipo() == TipoLinea.PARTICULAR) {
			res.setImporteIva(res.getLineaFactura().getImporteIva());
			res.setDescuento(0d);
			res.setTotal(res.getLineaFactura().getImporteConsumido()
					+ res.getImporteIva());
		} else { // sin iva y con descuento, o no
			res.setImporteIva(0d);

			if (lf.getLineaTelefonica().getPoseeDescuento()) {
				res.setDescuento(vigente.getSubvencionCorporacion());
			} else {
				res.setDescuento(0d);
			}

			// caso de descontar mas de lo que ha consumido, dejar a cero
			if (res.getDescuento() >= res.getLineaFactura()
					.getImporteConsumido()) {
				res.setDescuento(res.getLineaFactura().getImporteConsumido());
				res.setTotal(0d);
			} else {
				res.setTotal(res.getLineaFactura().getImporteConsumido()
						- res.getDescuento());
			}
		}

		return res;
	}

	/**
	 * Preparamos una estructura de datos a medida para el informe JasperReports
	 * 
	 * @param lineasFacturaSalida
	 * @param inicioNumeracionFactura
	 * @return
	 * @throws IllegalArgumentException
	 *             si tiposlinea esta vacio
	 */
	public static List<LineaInformeFactura> loadDatosInforme(
			final List<LineaFacturaSalida> lineasFacturaSalida,
			Integer inicioNumeracionFactura, Collection<TipoLinea> tiposLinea) {

		List<LineaInformeFactura> res = null;

		if (inicioNumeracionFactura == null) {
			inicioNumeracionFactura = 0;
		}

		if (tiposLinea == null || tiposLinea.isEmpty()) {
			throw new IllegalArgumentException(
					"Imposible generar el informe para ningun tipo de lineas telefonicas");
		}

		ApplicationContext ctx = AppContext.getApplicationContext();
		Parametros vigente = ctx.getBean(ParametrosService.class)
				.buscarViegente();

		Map<Empleado, List<LineaFacturaSalida>> tmp = new HashMap<Empleado, List<LineaFacturaSalida>>();

		// creamos mapa a medida
		TipoLinea tl = null;
		for (LineaFacturaSalida lfs : lineasFacturaSalida) {

			tl = lfs.getLineaFactura().getLineaTelefonica().getTipo();
			if (!tiposLinea.contains(tl)) {
				continue;
			}

			Empleado e = lfs.getLineaFactura().getLineaTelefonica()
					.getTitular();
			if (tmp.get(e) == null) {
				tmp.put(e, new LinkedList<LineaFacturaSalida>());
			}
			tmp.get(e).add(lfs);
		}

		res = new ArrayList<LineaInformeFactura>(tmp.size());

		for (Empleado e : tmp.keySet()) {
			LineaInformeFactura li = new LineaInformeFactura();
			li.setEmpleado(e);
			li.setLineas(tmp.get(e));

			String formateado = StringUtils.leftPad(""
					+ inicioNumeracionFactura++, 5, '0');
			li.setCodigoFactura(vigente.getPrefijoCodigoFactura()
					+ (formateado));

			res.add(li);
		}

		return res;
	}

	public static void main(String[] args) {
		Double d = 55.567;

		BigDecimal bd = new BigDecimal(d);
		bd = bd.setScale(0, BigDecimal.ROUND_HALF_UP);

		System.out.println(bd.intValue());
	}

}
